package test;

import library.DaoUtil;
import library.ErrorCode;
import library.controller.BookController;
import library.controller.BorrowController;
import library.controller.ReaderController;
import library.entity.Book;
import library.entity.BookingRecord;
import library.entity.Reader;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.sql.SQLException;
import java.util.Calendar;
import java.util.List;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

public class SystemTestBooking{
	private Reader testReader;
	private BorrowController_test booking;
	private TestData testData;
	
	public class BorrowController_test extends BorrowController{
		// Class extend from borrow controller for test purpose 
		public BorrowController_test(Reader reader) throws SQLException {
			super(reader);
			// TODO Auto-generated constructor stub
		}
		
		public void setDate(Calendar date){
			this.today = date;
		}
	}
	
	@Before
	public void setUp() throws Exception{
		DaoUtil.init();
		testData = new TestData();
		testReader = testData.getTestReader();
		booking = new BorrowController_test(testReader);
		booking.borrowBook(1);
	}
	 
	/*
	 *  Begin of MC/DC Testing of booking function  
	 */
	
	@Test
	public void testSuccessBorrow(){
		boolean isSuccess = booking.borrowBook(2);
		assertTrue(isSuccess);
	}
	
	@Test
	public void borrowNotExistBook(){
		boolean isSuccess = booking.borrowBook(-999);
		assertFalse(isSuccess);
		assertEquals(ErrorCode.BOOK_NOT_FOUND, booking.getError().getErrorCode());
	}
	
    @Test
    public void borrowBookTwice() {
    	boolean isSuccess = booking.borrowBook(1);
        assertFalse(isSuccess);
        assertEquals(ErrorCode.BOOK_ALREADY_RESERVED, booking.getError().getErrorCode());
    }
    
    @Test
    public void userExpireBorrow() throws SQLException{
    	testData.returnAllBorrowRecord();    	
    	booking.borrowBook(1); // to add a borrow record
    	 
    	Calendar futher_date = Calendar.getInstance();
    	// change current date to a mouth after, the system will 'think' the previous borrow record is late
    	futher_date.add(Calendar.MONTH, 1); 
    	booking.setDate(futher_date);
    	boolean isSuccess = booking.borrowBook(3);
        assertFalse(isSuccess);
        assertEquals(ErrorCode.READER_HAVE_EXPIRE_BOOK, booking.getError().getErrorCode());    	
    }
    
	/*
	 *  End of MC/DC Testing of booking function  
	 */
     
    
    
    /*
     * Other function test
     */
    
    @Test
    public void checkBookRecord() {
        List<BookingRecord> result = booking.getBookingRecord();
        assertEquals(testData.getBook(1).getName(), result.get(0).getBook().getName());
    }    
    
    @Test
    public void returnBook() {        
        Boolean result = booking.returnBook(testData.getBook(1));
        assertTrue(result);
    }
    
    @Test
    public void renewBook(){
    	BookingRecord record = booking.getBookingRecord().get(0);
    	assertTrue(booking.renew(record));
    	Calendar retrnDate = Calendar.getInstance();
    	retrnDate.add(Calendar.DATE, booking.loanDate);
    	record = booking.getBookingRecord().get(0);
    	System.out.println(retrnDate.toString());
    	System.out.println(record.getReturnDate().toString());
    	assertEquals(record.getReturnDate().get(Calendar.DAY_OF_YEAR),retrnDate.get(Calendar.DAY_OF_YEAR));
    }
    
    @Test
    public void renewBookManyTime(){
    	BookingRecord record = booking.getBookingRecord().get(0);
    	for(int i=0;i<booking.maxBorrowCount;i++){
    		booking.renew(record);
    	}
    	assertFalse(booking.renew(record));
    	assertEquals(ErrorCode.RENEW_FAIL_MAX_COUNT_EXCESS,booking.getError().getErrorCode());
    }
    @Test
    public void borrowBookManyTime(){
    	int i=3,j=0;
    	while(j<booking.maxBorrowCount-1){
    		if(booking.borrowBook(i))
    			j++;
    		i++;
    	}
    	assertFalse(booking.borrowBook(2));
    	assertEquals(ErrorCode.RENEW_FAIL_MAX_COUNT_EXCESS,booking.getError().getErrorCode());
    }
    
    @After
    public void cleanup(){
    	testData.returnAllBorrowRecord();
    }   
}
